using System.Text;
using Gateway.IQuery.Sign;
using Gateway.Query;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;

namespace Gateway.UI.Api.Extensions;

/// <summary>
/// 
/// </summary>
public static class AuthenticationExtension
{
    
    /// <summary>
    /// 添加认证
    /// </summary>
    /// <param name="services"></param>
    /// <param name="configuration"></param>
    /// <param name="func"></param>
    /// <exception cref="ArgumentNullException"></exception>
    public static void AddMyAuthentication(this IServiceCollection services,
        IConfiguration configuration, Func<MessageReceivedContext, Task> func = null)
    {
        services.AddTransient<ITokenService, TokenService>();
        var jwtKeyConfig = JsonConvert.DeserializeObject<JwtKeyConfig>(configuration["Jwt"]);
        if (jwtKeyConfig == null)
            throw new ArgumentNullException(nameof(JwtKeyConfig), "调用 AddJwtAuthentication 配置时出错，未找到配置。");
        services.Configure<JwtKeyConfig>(x =>
        {
            x.SecurityKey = jwtKeyConfig.SecurityKey;
            x.Issuer = jwtKeyConfig.Issuer;
            x.Audience = jwtKeyConfig.Audience;
            x.Expire = jwtKeyConfig.Expire;
        });

        //添加jwt验证
        services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                options.Challenge = JwtBearerDefaults.AuthenticationScheme;
                options.RequireHttpsMetadata = false;

                if (!string.IsNullOrEmpty(jwtKeyConfig.Audience))
                    options.Audience = jwtKeyConfig.Audience;

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = jwtKeyConfig.Issuer,
                    //缓冲过期时间，总的有效时间等于这个时间加上过期时间
                    ClockSkew = TimeSpan.FromMinutes(jwtKeyConfig.ClockSkew),
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKeyConfig.SecurityKey))
                };

                options.Events = new JwtBearerEvents
                {
                    OnMessageReceived = (context) =>
                    {
                        if (null != func)
                            return func.Invoke(context);
                        var accessToken = context.Request.Query["access_token"];
                        var path = context.HttpContext.Request.Path;
                        if (!string.IsNullOrWhiteSpace(accessToken) &&
                            path.StartsWithSegments("/api/signalr"))//这里可以修改为你相应的hub地址
                        {
                            context.Token = accessToken;
                        }

                        return Task.CompletedTask;
                    }
                };
            });
    }
}